<?php
/**
 * Created by PhpStorm.
 * User: TheLuther
 * Date: 2019/11/10
 * Time: 21:14
 */
namespace app\common\model;

use think\App;
use think\Exception;
use think\Model;
use think\Db;
use think\Config;
use app\common\model\User as UserModel;
use app\common\model\FormField as FormFieldModel;
use app\common\model\FormFormat;
use think\facade\Request;
use think\Validate;


class Form extends model{
    protected static $instance;
    public static function instance($options = [])
    {
        if (is_null(self::$instance)) {
            self::$instance = new self($options);
        }
        return self::$instance;
    }

    public function getSingle($where){
        return Db::name('form')->where($where)->findOrEmpty();
    }

    public function add($data){
        $data['guid'] = guid();
        $maintable = $data['maintable'];
        $extratable = $data['extratable'];

        if ( $this->hasTable($maintable) ){
            return '主表已存在';
        }
        if ( $extratable && $this->hasTable($extratable) ){
            return '附表已存在';
        }

        $table = config('database.prefix') . strtolower($maintable);
        $sql = <<<EOF
				CREATE TABLE `{$table}` (
				`guid` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'GUID',
				`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '标题',
				`addtime` int(10) unsigned NOT NULL DEFAULT '0'  COMMENT '创建时间',
				`edittime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
				`url` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '链接地址',
				`uid` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '用户id',
				`uname` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '用户名',
				`clientip` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '用户IP',
                `status` tinyint(2) NOT NULL DEFAULT '0' COMMENT '状态',
				PRIMARY KEY (`guid`)
				) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='{$data['name']}模型表';
EOF;
        try{
            Db::execute($sql);
            $field = array('sort'=>100,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'guid','title'=>'guid','remark'=>'','pattern'=>'','errortip'=>'','type'=>'textbox','sql'=>"char(64) not null default ''","configs"=>"",'ismain'=>true,'isrequire'=>false,'ispostshow'=>false,'show'=>false,'status'=>true,'showintable'=>false,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>99,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'title','title'=>'标题','remark'=>'','pattern'=>'','errortip'=>'','type'=>'textbox','sql'=>"char(255) not null default ''","configs"=>"",'ismain'=>true,'isrequire'=>true,'ispostshow'=>true,'show'=>true,'status'=>true,'showintable'=>true,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>98,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'url','title'=>'链接地址','remark'=>'','pattern'=>'','errortip'=>'','type'=>'textbox','sql'=>"char(255) not null default ''","configs"=>"",'ismain'=>true,'isrequire'=>true,'ispostshow'=>true,'show'=>true,'status'=>true,'showintable'=>false,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>80,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'addtime','title'=>'创建时间','remark'=>'','pattern'=>'','errortip'=>'','type'=>'date','sql'=>"int(10) not null default '0'","configs"=>"{\"format\":\"yyyy-MM-dd HH:mm:ss\"}",'ismain'=>true,'isrequire'=>true,'ispostshow'=>true,'show'=>true,'status'=>true,'showintable'=>true,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>79,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'edittime','title'=>'更新时间','remark'=>'','pattern'=>'','errortip'=>'','type'=>'date','sql'=>"int(10) not null default '0'","configs"=>"{\"format\":\"yyyy-MM-dd HH:mm:ss\"}",'ismain'=>true,'isrequire'=>true,'ispostshow'=>true,'show'=>true,'status'=>true,'showintable'=>true,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>78,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'uid','title'=>'用户ID','remark'=>'','pattern'=>'','errortip'=>'','type'=>'textbox','sql'=>"int(10) not null default '0'","configs"=>"",'ismain'=>true,'isrequire'=>false,'ispostshow'=>true,'show'=>false,'status'=>true,'showintable'=>false,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>77,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'uname','title'=>'用户名','remark'=>'','pattern'=>'','errortip'=>'','type'=>'textbox','sql'=>"char(255) not null default ''","configs"=>"",'ismain'=>true,'isrequire'=>false,'ispostshow'=>true,'show'=>false,'status'=>true,'showintable'=>true,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>76,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'clientip','title'=>'用户IP','remark'=>'','pattern'=>'','errortip'=>'','type'=>'textbox','sql'=>"char(64) not null default ''","configs"=>"",'ismain'=>true,'isrequire'=>false,'ispostshow'=>true,'show'=>false,'status'=>true,'showintable'=>false,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
            $field = array('sort'=>60,'guid'=>guid(),'formid'=>$data['guid'],'name'=>'status','title'=>'状态','remark'=>'','pattern'=>'','errortip'=>'','type'=>'radio','sql'=>"tinyint(2) not null default '0'","configs"=>"{\"defaultval\":\"0\",\"values\":\"-1|\u5df2\u5220\u9664,0|\u5f85\u5ba1\u6838,1|\u5ba1\u6838\u4e2d,9|\u5df2\u5ba1\u6838\"}",'ismain'=>true,'isrequire'=>true,'ispostshow'=>true,'show'=>true,'status'=>true,'showintable'=>true,'addtime'=>time(),'edittime'=>time());
            Db::name('form_field')->insert($field);
        }
        catch (Exception $ex){
            return $ex->getMessage();
        }

        if($extratable){
            $table = config('database.prefix') . strtolower($extratable);
            $sql = <<<EOF
				CREATE TABLE `{$table}` (
				`_guid` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'GUID',
				PRIMARY KEY (`_guid`)
				) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='{$data['name']}附表';
EOF;
            try{
                Db::execute($sql);
            }
            catch (Exception $ex){
                return $ex->getMessage();
            }
        }
        try{
            Db::name('form')->insert($data);
            $this->addFormMenu($data);
            return true;
        }
        catch (Exception $ex){
            return $ex->getMessage();
        }
    }

    public function edit($data){
        $form = Db::name('form')->where(['guid'=>$data['guid']])->findOrEmpty();
        if(!$form)
            return '参数错误';
        try{
            if($form['maintable'] != $data['maintable']){
                $tablepre = config('database.prefix');
                $sql = "alter table ".$tablepre.$form['maintable']."  rename to ".$tablepre.$data['maintable'];
                Db::execute($sql);
            }
            if($form['extratable'] != $data['extratable']){
                $tablepre = config('database.prefix');
                try{
                    if(empty($form['extratable'])){
                        $table = $tablepre . strtolower($data['extratable']);
                        $sql = <<<EOF
                            CREATE TABLE `{$table}` (
                            `_guid` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'GUID',
                            PRIMARY KEY (`_guid`)
                            ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='{$data['name']}模型附表';
EOF;
                        Db::execute($sql);
                    }
                    else if(empty($data['extratable'])){
                        $sql = "drop table ".$tablepre.$form['extratable'];
                        Db::execute($sql);
                    }
                    else{
                        $sql = "alter table ".$tablepre.$form['extratable']."  rename to ".$tablepre.$data['extratable'];
                        Db::execute($sql);
                    }
                }
                catch (Exception $ex){
                    return $ex->getMessage();
                }
            }
            Db::name('form')->where(['guid'=>$data['guid']])->update($data);
            if( $data['module']!=$form['module'] ){
                $this->removeFormMenu($form);
                $this->addFormMenu($data);
            }else{
                $updatearray = array();
                $updatearray['name'] = $data['name'].'管理';
                $updatearray['sort'] =  $data['sort'];
                $updatearray['icon'] =  $data['icon'];
                Db::name('auth')->where(['guid'=>$data['guid']])->update($updatearray);
            }
            return true;
        }
        catch (Exception $ex){
            return $ex->getMessage();
        }
    }

    public function remove($where){
        try{
            $form = Db::name('form')->where($where)->findOrEmpty();
            if(!$form)
                return '参数错误';
            $tablepre = config('database.prefix');
            $sql = "drop table ".$tablepre.$form['maintable'];
            Db::execute($sql);
            if($form['extratable']){
                $sql = "drop table ".$tablepre.$form['extratable'];
                Db::execute($sql);
            }
            Db::name('form')->where($where)->delete();
            Db::name('form_field')->where(['formid'=>$form['guid']])->delete();
            Db::name('auth')->where($where)->delete();
            $this->removeFormMenu($form);
            return true;
        }
        catch (Exception $ex){
            return $ex->getMessage();
        }
    }

    private function hasTable($tablename){
        $table = config("database.prefix") . strtolower($tablename);
        if (true == Db::query("SHOW TABLES LIKE '{$table}'")) {
            return true;
        } else {
            return false;
        }
    }

    private function addFormMenu($data){
        $formguid = $data['guid'];
        $name = $data['name'];
        $module = $data['module'];
        $icon = $data['icon'];
        try{
            $menuform = array();
            $menuform['guid'] = $formguid;
            $menuform['pid'] = '';
            $menuform['name'] = $name.'管理';
            $menuform['sort'] = 50;
            $menuform['icon'] = $icon;
            $menuform['ismenu'] = true;
            Db::name('auth')->insert($menuform);

            $menuguid = guid();
            $menuform = array();
            $menuform['guid'] = $menuguid;
            $menuform['pid'] = $formguid;
            $menuform['name'] = '内容列表';
            $menuform['action'] = $module.'/admin/listing';
            $menuform['sort'] = 50;
            $menuform['icon'] = 'fa fa-align-justify';
            $menuform['ismenu'] = true;
            Db::name('auth')->insert($menuform);

            $menuform = array();
            $menuform['guid'] = guid();
            $menuform['pid'] = $menuguid;
            $menuform['name'] = '添加';
            $menuform['action'] = $module.'/admin/add';
            $menuform['sort'] = 50;
            $menuform['ismenu'] = false;
            Db::name('auth')->insert($menuform);

            $menuform = array();
            $menuform['guid'] = guid();
            $menuform['pid'] = $menuguid;
            $menuform['name'] = '编辑';
            $menuform['action'] = $module.'/admin/edit';
            $menuform['sort'] = 50;
            $menuform['ismenu'] = false;
            Db::name('auth')->insert($menuform);

            $menuform = array();
            $menuform['guid'] = guid();
            $menuform['pid'] = $menuguid;
            $menuform['name'] = '删除';
            $menuform['action'] = $module.'/admin/remove';
            $menuform['sort'] = 50;
            $menuform['ismenu'] = false;
            Db::name('auth')->insert($menuform);
            copyDir('../application/common/template','../application/'.$module);
            $filelist = getDirFiles('../application/'.$module,true);
            foreach($filelist as $file){
                if(is_dir($file))
                    continue;
                $content = file_get_contents($file);
                $content = str_replace('__moduleclass__',ucfirst($module),$content);
                $content = str_replace('__module__',$module,$content);
                $content = str_replace('__formid__',$formguid,$content);
                file_put_contents($file,$content);
            }
            @rename('../application/'.$module.'/model/Model.php','../application/'.$module.'/model/'.ucfirst($module).'.php');
            @rename('../application/'.$module.'/validate/Model.php','../application/'.$module.'/validate/'.ucfirst($module).'.php');
            @chmod('../application/'.$module,0777);
            return true;
        }
        catch (Exception $ex){
            return $ex->getMessage();
        }
    }

    private function removeFormMenu($data){
        $formguid = $data['guid'];
        $module = $data['module'];
        try{
            Db::name('auth')->where(['guid'=>$formguid])->delete();
            $listmenu = Db::name('auth')->where(['action'=>$module.'/admin/listing'])->findOrEmpty();
            if($listmenu){
                Db::name('auth')->where(['pid'=>$formguid])->delete();
                Db::name('auth')->where(['pid'=>$listmenu['guid']])->delete();
            }
            removeDir('../application/'.$module);
        }catch (Exception $ex){
            return $ex->getMessage();
        }
    }

    public function getFormData($formid,$guid=''){
        $form = Db::name('form')->where(['guid'=>$formid])->findOrEmpty();
        if(!$form)
            return null;
        $fields = FormFieldModel::instance()->getFields($formid);
        if(!$fields)
            return null;
        $maintable = $form['maintable'];
        $extratable = $form['extratable'];

        $model = Db::name($maintable)->alias('a');
        if($extratable)
            $model = $model->join($extratable.' b','a.guid=b._guid');
        if(empty($guid))
            $guid = '0000000000000000';
        $field = 'a.*';
        if($extratable)
            $field.= ',b.*';
        $model = $model->field($field)->where(['guid'=>$guid])->findOrEmpty();
        return $model;
    }

    public function addFormData($formid,$data){
        $form = Db::name('form')->where(['guid'=>$formid])->findOrEmpty();
        if(!$form)
            return '参数错误';
        $fields = FormFieldModel::instance()->getFields($formid);
        if(!$fields)
            return '参数错误';
        $maintable = $form['maintable'];
        $extratable = $form['extratable'];
        $maindata = array();
        $extradata = array();

        if(empty($data['guid']))
            $data['guid'] = guid();
        try {
            foreach ($fields as $k => $v) {
                if ( !key_exists($v['name'], $data) )
                    continue;
                $res = FormHelper::instance()->format($v,$data);
                if($res['error'] == true)
                    return $res['msg'];

                if ($v['ismain']) {
                    $maindata[$v['name']] = $res['val'];
                } else {
                    $extradata[$v['name']] = $res['val'];
                }
            }
            $extradata['_guid'] = $data['guid'];
            Db::name($maintable)->insert($maindata);
            if ($extratable) {
                Db::name($extratable)->insert($extradata);
            }
            return true;
        }
        catch(Exception $ex){
            return $ex->getMessage();
        }
    }

    public function editFormData($formid,$guid,$data){
        $form = Db::name('form')->where(['guid'=>$formid])->findOrEmpty();
        if(!$form)
            return '参数错误';
        $fields = FormFieldModel::instance()->getFields($formid);
        if(!$fields)
            return '参数错误';
        $maintable = $form['maintable'];
        $extratable = $form['extratable'];
        $maindata = array();
        $extradata = array();

        $data['guid'] = $guid;
        foreach($fields as $k=>$v){
            if ( !key_exists($v['name'], $data) )
                continue;
            $res = FormHelper::instance()->format($v,$data);
            if($res['error'] == true)
                return $res['msg'];

            if ($v['ismain']) {
                $maindata[$v['name']] = $res['val'];
            } else {
                $extradata[$v['name']] = $res['val'];
            }
        }
        $extradata['_guid'] = $data['guid'];
        Db::name($maintable)->where(['guid'=>$guid])->update($maindata);
        if($extratable){
            $extradata['_guid'] = $guid;
            Db::name($extratable)->where(['_guid'=>$guid])->update($extradata);
        }
        return true;
    }

    public function removeFormData($formid,$guid){
        $form = Db::name('form')->where(['guid'=>$formid])->findOrEmpty();
        if(!$form)
            return '参数错误';
        $maintable = $form['maintable'];
        $extratable = $form['extratable'];
        try{
            Db::name($maintable)->where(['guid'=>$guid])->delete();
            if($extratable)
                Db::name($extratable)->where(['_guid'=>$guid])->delete();
            return true;
        }catch (Exception $ex){
            return $ex->getMessage();
        }
    }

    public function getPageDataList($formid,$where,$order,$page,$pagesize){
        $form = Db::name('form')->where(['guid'=>$formid])->findOrEmpty();
        $maintable = $form['maintable'];
        $extratable = $form['extratable'];
        $fields = FormFieldModel::instance()->getFields($formid);
        $mainfields = array();
        $extrafields = array();
        $showfields = array();

        foreach($fields as $k=>$v){
            if($v['ismain']){
                $mainfields[] = $v;
                if($v['showintable'])
                    $showfields[] = 'a.'.$v['name'];
            }
            else{
                $extrafields[] = $v;
                if($v['showintable'])
                    $showfields[] = 'b.'.$v['name'];
            }
        }
        $showfields = implode(',',$showfields);

        $list = Db::name($maintable)->alias('a');
        if($extratable)
            $list = $list->join($extratable.' b','a.guid=b._guid');
        $count = $list->where($where)->count();
        $list = $list->field($showfields)->where($where)->order($order)->page($page,$pagesize)->select();
        return array('list'=>$list,'count'=>$count);
    }

}